﻿using Minecraft.Config;
using Minecraft.Config.Csv.CsvCls;
using Minecraft.Config.Csv.CsvCom;
using Minecraft.Model;
using Minecraft.Model.Furniture;
using Minecraft.Model.ReqResp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Minecraft.ServerHall
{
	public static class FurnitureOutputRepairExt
	{
		/// <summary>
		/// 获取产出家具修理信息
		/// </summary>
		/// <param name="furniture"></param>
		/// <param name="session"></param>
		/// <param name="furnitureOutputRepairInfo"></param>
		/// <returns></returns>
		public static FurnitureOutputRepairInfo GetFurnitureOutputRepairInfo(this FurnitureModel furniture, MinecraftSession session)
		{
			var timeNow = DateTimeOffset.Now;

			//if (JsonConfig.Value.IsDebug)
			//{
			//	furniture.Repair_MaterialGoodsItemIdsAndNums = "100000#20|100002#20|100004#20|100009#20";
			//	furniture.Repair_StartTime = timeNow.AddSeconds(-1801);
			//}

			/*
			 * 逻辑：
			 * 判断修理条件：得到修理状态
			 *	达到修理条件：
			 *		判断修理持续时间：
			 *		修理持续时间小于修理总时间：
			 *			修理状态为【进行中】
			 *		修理持续时间大于等于修理总时间：
			 *			修理状态为【未开始】
			 *	未达到修理条件：
			 *		修理状态为【未开始】
			 */
			int totalSeconds = 0;
			int remainSeconds = 0;
			EnumFurnitureOutputRepairState enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.NotStart;
			if (!furniture.Repair_State_Convert)
			{
				enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.NotStart;
			}
			else
			{
				Mod_Drawing csvFurnitureInfo = furniture.GetMod_FurnitureInfo();
				if (furniture.Hp > 0)
				{
					enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.NotStart;
					furniture.Repair_State = 0;

					//耐久度自增恢复
					if (furniture.Hp < csvFurnitureInfo.Hp_Convert)
					{
						int incrementSeconds = 60; //增量（单位：s）（即每分钟增加n个）
						var timeSeconds = Convert.ToInt32(timeNow - furniture.Repair_StartTime);
						var num = timeSeconds / incrementSeconds; //个数
						var mod = timeSeconds % incrementSeconds; //余数
						furniture.Hp += num;
						if (furniture.Hp > csvFurnitureInfo.Hp_Convert)
						{
							furniture.Hp = csvFurnitureInfo.Hp_Convert;
							furniture.Repair_StartTime = timeNow;
						}
						else
						{
							furniture.Repair_StartTime = furniture.Repair_StartTime.AddSeconds(incrementSeconds * num);
						}
					}
				}
				else
				{
					var repairModRecipeTimeInfo = csvFurnitureInfo.GetRepairModRecipeTimeInfoList_Convert(furniture.Level);
					totalSeconds = repairModRecipeTimeInfo.Second;
					var isCanAchieveRepair = furniture.GetFurnitureOutputRepairState(session);
					if (isCanAchieveRepair)
					{
						var sustainedSeconds = Convert.ToInt32((timeNow - furniture.Repair_StartTime).TotalSeconds);
						if (sustainedSeconds < repairModRecipeTimeInfo.Second)
						{
							enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.Progressing;
							remainSeconds = repairModRecipeTimeInfo.Second - sustainedSeconds;
						}
						else
						{
							enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.NotStart;
							furniture.Repair_State = 0;
							//已经修理完成，初始化数据
							var listCopy = furniture.GetFurnitureOutputRepairMaterialGoodsInfoList_Convert().DeepCopy();
							for (int i = 0; i < listCopy.Count(); i++)
							{
								var item = listCopy[i];
								item.Num = 0;
								furniture.TransformListToOutput_RepairMaterialGoodsItemIdsPosAndNums_Convert(item);
							}
							//hp变为最大初始化值
							furniture.Hp = csvFurnitureInfo.Hp_Convert;
							//刷新开始修理的时间
							furniture.Repair_StartTime = furniture.Repair_StartTime.AddSeconds(repairModRecipeTimeInfo.Second);
						}
					}
					else
					{
						enumFurnitureOutputRepairState = EnumFurnitureOutputRepairState.NotStart;
						furniture.Repair_State = 0;
					}
				}
			}

			FurnitureOutputRepairInfo furnitureOutputRepairInfo = new FurnitureOutputRepairInfo
			{
				enumFurnitureOutputRepairState = enumFurnitureOutputRepairState,
				furnitureOutputRepairMaterialInfoList = furniture.GetFurnitureOutputRepairMaterialGoodsInfoList_Convert(),
				totalSeconds = totalSeconds,
				remainSeconds = remainSeconds,
			};
			if (JsonConfig.Value.IsTest)
			{
				//测试，记录结果日志
				string result = $"临时记录：时间：{timeNow.ToStr()}，家具修理结果：{furnitureOutputRepairInfo.JsonSerialize()}";
				session.AppServer.Logger.Debug(result);
			}
			return furnitureOutputRepairInfo;
		}
		/// <summary>
		/// 针对 Repair_MaterialGoodsItemIdsAndNums 字段转换成产出家具修理已经有的材料物品信息列表
		/// </summary>
		/// <param name="furniture"></param>
		/// <returns></returns>
		public static List<FurnitureOutputRepairMaterialInfo> GetFurnitureOutputRepairMaterialGoodsInfoList_Convert(this FurnitureModel furniture)
		{
			Mod_Drawing csvFurnitureInfo = furniture.GetMod_FurnitureInfo();
			if (furniture.Hp > 0)
			{
				return new List<FurnitureOutputRepairMaterialInfo>();
			}

			//加上汇总排序机制，目前先按照itemid排序

			List<FurnitureOutputRepairMaterialInfo> furnitureOutputRepairMaterialInfoList = new List<FurnitureOutputRepairMaterialInfo>();
			var itemidsAndNumsStrs = furniture.Repair_MaterialGoodsItemIdsAndNums.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (var itemidsAndNumsStr in itemidsAndNumsStrs)
			{
				var idsAndNums = itemidsAndNumsStr.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries);
				FurnitureOutputRepairMaterialInfo furnitureOutputMaterialGoodsInfo = new FurnitureOutputRepairMaterialInfo
				{
					GoodsItemId = idsAndNums[0],
					Num = int.Parse(idsAndNums[1])
				};
				furnitureOutputRepairMaterialInfoList.Add(furnitureOutputMaterialGoodsInfo);
			}

			var RepairCompositing = csvFurnitureInfo.GetRepairCompositingList_Convert(furniture.Level);
			int position = -1;
			furnitureOutputRepairMaterialInfoList = RepairCompositing.modRecipeInfoList_Convert.ConvertAll(r =>
			{
				var materialInfo = furnitureOutputRepairMaterialInfoList.FirstOrDefault(m => m.GoodsItemId == r.GoodsItemId);
				if (materialInfo != null)
				{
					return new FurnitureOutputRepairMaterialInfo
					{
						GoodsItemId = materialInfo.GoodsItemId,
						needNum = r.Num,
						Num = materialInfo.Num
					};
				}
				else
				{
					return new FurnitureOutputRepairMaterialInfo
					{
						GoodsItemId = r.GoodsItemId,
						needNum = r.Num,
						Num = 0,
					};
				}
			})
			.OrderBy(m => m.GoodsItemId)
			.ToList().ConvertAll(r =>
			{
				position++;
				return new FurnitureOutputRepairMaterialInfo()
				{
					GoodsItemId = r.GoodsItemId,
					position = position,
					needNum = r.needNum,
					Num = r.Num
				};
			}).ToList();

			return furnitureOutputRepairMaterialInfoList;
		}
		/// <summary>
		/// 针对 Repair_MaterialGoodsItemIdsAndNums 字段的修改要从对象列表转换成字符串
		/// </summary>
		/// <param name="furniture"></param>
		/// <param name="furnitureOutputMaterialGoodsInfo"></param>
		public static void TransformListToOutput_RepairMaterialGoodsItemIdsPosAndNums_Convert(this FurnitureModel furniture,
			FurnitureOutputRepairMaterialInfo furnitureOutputRepairMaterialInfo)
		{
			var list = furniture.GetFurnitureOutputRepairMaterialGoodsInfoList_Convert();
			var index = list.FindIndex(m => m.GoodsItemId == furnitureOutputRepairMaterialInfo.GoodsItemId);
			if (index >= 0)
			{
				list.RemoveAt(index);
			}
			list.Add(furnitureOutputRepairMaterialInfo);
			furniture.Repair_MaterialGoodsItemIdsAndNums = string.Join("|", list.ToList().ConvertAll(info =>
			{
				return string.Join("#", info.GoodsItemId, info.Num);
			}).ToArray());
		}
		/// <summary>
		/// （针对产出家具，修理）是否满足产出家具修理条件
		/// </summary>
		/// <param name="furniture"></param>
		/// <param name="session"></param>
		/// <returns></returns>
		public static bool GetFurnitureOutputRepairState(this FurnitureModel furniture, MinecraftSession session)
		{
			//耐久度hp是否小于等于0，材料是否足够

			if (furniture.Hp > 0)
			{
				return false;
			}
			//家具的配置信息
			Mod_Drawing csvFurnitureInfo = furniture.GetMod_FurnitureInfo();
			if (csvFurnitureInfo == null) //家具表中该家具配置不存在，则数据库信息存在错误，或者配置表出现错误
			{
				string errorTips = $"指定家具配置信息不存在（FurnitureItemId：【{furniture.FurnitureItemId}】）";
				session.AppServer.Logger.Fatal(errorTips);
				return false;
			}
			var isCanAchieveRepair = furniture.GetFurnitureOutputRepairMaterialGoodsInfoList_Convert().All(m => m.Num >= m.needNum);
			return isCanAchieveRepair;
		}
	}
}
